//
//  CardIOChargeRequest.h
//  Copyright (c) 2011-2012 Lumber Labs, Inc. All rights reserved.
//

#import <Foundation/Foundation.h>

// CardIOChargeRequests are used to summarize a credit card charge.
@interface CardIOChargeRequest : NSObject<NSCopying> {
@private
  NSString *currency;
  NSString *note;
  void *context;
  NSArray *items;
  NSString *appToken;
  BOOL live;
}

// Required. card.io appToken; get one from https://www.card.io/
@property(nonatomic, copy, readwrite) NSString *appToken;

// Required. If YES, real money exchanges hands. If NO, the request occurs in a sandbox.
// Defaults to NO -- don't forget to set this to YES for production use!
@property(nonatomic, assign, readwrite) BOOL live;

// Required. Must be @"USD".
// Note that all amounts are represented in *cents*.
@property(nonatomic, copy, readwrite) NSString *currency;

// Optional. A note about this charge; intended for your use, not displayed to users.
// This will be stored on the card.io servers; do not put sensitive data here!
// Maximum length: 100 characters. Longer strings may be silently truncated.
@property(nonatomic, copy, readwrite) NSString *note;

// Optional. A non-retained context pointer for passing data through to your delegate methods.
@property(nonatomic, assign, readwrite) void *context;

// Required. The items you are charging the user for.
// Each item in items must have a value for two keys:
//   CardIOChargeItemKeyAmount ==> NSNumber containing an amount to charge, currently in *cents* (for USD, the only supported currency), so 100 == $1.
//   CardIOChargeItemKeyDescription ==> NSString containing a short, non-empty description of the item, suitable for display to the user.
// The simplest way to create such an item is with an NSDictionary with these two keys.
// There is a convenience method for creating such dictionaries: +itemWithDescription:amount:.
// When a CardIOChargeRequest is copied, all valid items in the resulting copy are converted to NSDictionaries;
// invalid items are passed through unchanged.
@property(nonatomic, copy, readwrite) NSArray *items;

// Calculated sum of amounts across all items. Yields -1 in case of error (e.g. if one of the items is not valid).
@property(nonatomic, assign, readonly) NSInteger totalAmount;

// Formatted total amount appropriate for display.
@property(nonatomic, retain, readonly) NSString *formattedTotalAmount;

// Checks whether the charge request appears valid.
// A charge request could be invalid due to:
//  * total amount too small (less than 100 == $1 USD)
//  * total amount too large (greater than 100000 = $1000 USD)
//  * no items
//  * invalid items (see items property above for specifications)
//  * no appToken
// Note that not all validity checks can be performed locally, such as checking the validity of the appToken.
// This method only performs local checks.
- (BOOL)isValid:(NSError **)error;

// Indicates whether a particular item dictionary is valid (amount and description both present).
+ (BOOL)itemIsValid:(id)item;
+ (BOOL)itemIsValid:(id)item error:(NSError **)error;

// Convenience method to create an item object given a description and an amount.
+ (NSDictionary *)itemWithDescription:(NSString *)description amount:(NSInteger)amount;

@end

extern NSString * const CardIOChargeItemKeyAmount; // = @"CardIOChargeItemKeyAmount"
extern NSString * const CardIOChargeItemKeyDescription; // = @"CardIOChargeItemKeyDescription"

// Request errors
extern NSString * const CardIOChargeRequestErrorDomain; // = @"CardIOChargeRequestErrorDomain"
extern NSInteger const CardIOChargeRequestErrorAmountTooSmall; // = -1
extern NSInteger const CardIOChargeRequestErrorAmountTooLarge; // = -2
extern NSInteger const CardIOChargeRequestErrorNoItems; // = -3
extern NSInteger const CardIOChargeRequestErrorInvalidItems; // = -4
extern NSInteger const CardIOChargeRequestErrorNoAppToken; // = -5
extern NSInteger const CardIOChargeRequestErrorInvalidAppToken; // = -6

// Errors of type CardIOChargeRequestErrorInvalidItems contain details in the userInfo dictionary;
// the invalid item is available via the CardIOChargeRequestItemInvalidObjectKey, and
// a more detailed error for that item is available via the CardIOChargeRequestItemInvalidErrorKey.
extern NSString * const CardIOChargeRequestItemInvalidObjectKey; // = @"CardIOChargeRequestItemInvalidObject"
extern NSString * const CardIOChargeRequestItemInvalidErrorKey; // = @"CardIOChargeRequestItemInvalidError"

// Individual item errors
extern NSString * const CardIOChargeRequestItemErrorDomain; // = @"CardIOChargeRequestItemErrorDomain"
extern NSInteger const CardIOChargeRequestItemErrorInvalidObject; // = -1
extern NSInteger const CardIOChargeRequestItemErrorInvalidAmount; // = -2
extern NSInteger const CardIOChargeRequestItemErrorInvalidDescription; // = -3

